package com.qianli.cashmama.trade.openApi.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.fqgj.base.services.redis.RedisClient;
import com.fqgj.base.services.redis.RedisKeyConsts;
import com.fqgj.common.utils.*;
import com.fqgj.exception.common.ApplicationException;
import com.fqgj.xjd.user.client.UserBankService;
import com.fqgj.xjd.user.client.enums.FrozenCodeEnum;
import com.fqgj.xjd.user.client.response.User;
import com.fqgj.xjd.user.client.response.UserAccessInfo;
import com.qianli.cashmama.product.facade.result.ProductCategory;
import com.qianli.cashmama.trade.bean.RedisKeyConstant;
import com.qianli.cashmama.trade.client.enums.OrderStatusSwitchEnum;
import com.qianli.cashmama.trade.common.enums.*;
import com.qianli.cashmama.trade.common.utils.HttpUtil;
import com.qianli.cashmama.trade.common.utils.TradeConfigUtil;
import com.qianli.cashmama.trade.dao.TBillDao;
import com.qianli.cashmama.trade.dao.TTradeDao;
import com.qianli.cashmama.trade.domain.model.TradeBase;
import com.qianli.cashmama.trade.domain.services.TradeBaseService;
import com.qianli.cashmama.trade.entity.TBillEntity;
import com.qianli.cashmama.trade.integration.product.ProductIntegrationService;
import com.qianli.cashmama.trade.integration.user.UserIntegrationService;
import com.qianli.cashmama.trade.openApi.controller.request.*;
import com.qianli.cashmama.trade.openApi.controller.response.OpenApiResult;
import com.qianli.cashmama.trade.openApi.controller.response.OpenApiResultCode;
import com.qianli.cashmama.trade.openApi.utils.encryption.ReceiveData;
import com.qianli.cashmama.trade.openApi.vendor.inner.vos.SendToMerchantData;
import com.qianli.cashmama.trade.repo.TradeBaseRepository;
import com.qianli.cashmama.trade.unique.TradeUniqueService;
import com.robert.vesta.util.IdUtils;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.util.*;

/**
 * @Author: cashmama
 * @Date: 2020/12/1-19:29
 * @Description: TODO
 * @Slogan: To be or not to be
 **/
@Service
@Log4j2
public class OpenApiService {
    @NacosValue(value = "${inner.push.token:8wIGjP1vTkAGhht1}", autoRefreshed = true)
    private String token;
    @NacosValue(value = "${inner.sync.push.domain:http://47.98.115.75:8087/gateway/6/38/gupta}", autoRefreshed = true)
    private String pushUrlDomain;
    private static String SELF_PRIVATE_KEY = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAMsFDM3N4rAZAtMNxXqbPhiqrSm2TMvveTJkJRX4vY2gAKix2jiHmZQQjLRnm84TY/m6D6YePeOqjUyjExOcPL9Xs5u1DRSbRgUhrXVAm+E128UeIIGrgHrrDQYazsuW2FbFoPs04BGPU0+yaTUZO3u7d0hobfXL+AMuMMQM+pMLAgMBAAECgYBMpT1uPTpFzUt5rotNfGp3GYiCZOadX21cDt7Jarz1SOC2z15ZVSgv9AeK3ErABCYMU6gwyN4Io4zwz+gV0ThFQE3INHjhaqNyn5UfslM/vP003GvdfgbuKitGcIyuO51Zx6Qipqqn/3sHEiO7HvVJEtbrbYHyUG2g8PM58f8S4QJBAPCc4ClN9RG5hjyS6pANRKfiKtmB8Ts+sQZD9o1f+Svyi8faYk0UFeUKxl+h+W/qYuMu/AFoBqtE8KORvjw8MCkCQQDYALrm2V0gVXVdgFyMennepkAheWZEIkqDct2kNHVAis9DvddEfYwwA+PjEO4ywlpBglyfK9i2dZkwQCzEywATAkBNT/rvCq+OLHCnkgVwl/LRhuiBzzD1+mTjQH8+WfI0XtDvPIqNfcCzQc0P+Xmurj9sBDLRON27toEj7baUoDpRAkA/oj9tgL2hp+tyhz08mVxLznh4JBaPnfaLsQxAsr+UKxCSaVwArmfdQVgibbtusrj6MZhtv/IRFqXxhAZsV02HAkBkvTCFTfSBjt5amXjlK306AsqsxLjdSjcjpWXguzBirPzUkJCOicFhtnKdHbk34Ys8EFE9OF+ptGQVm15cHfB/";
    @Autowired
    private TBillDao tBillDao;
    @Autowired
    private ProductIntegrationService productIntegrationService;
    @Autowired
    private TradeBaseRepository tradeBaseRepository;
    @Autowired
    private TradeBaseService tradeBaseService;
    @Autowired
    private TradeUniqueService tradeUniqueService;
    @Autowired
    private UserIntegrationService userIntegrationService;
    @Autowired
    private RedisClient redisClient;
    @Autowired
    private TradeConfigUtil apolloConfigUtil;

    @NacosValue(value = "${app.id:91C1000}", autoRefreshed = true)
    private String APP_ID;

    private static final String SELF_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCt7VzZd7zB9UpNBtAe7x6HWFK07Xr8RtQUSAN1XT6g+f9sc5FRMWXO0d7ApLt3+HUPPwbgLF23PMcrCTxbS+wuEzET5jVuanPwfcc66Z5aFZ8acxHj7a5xPrDQMlxPIAizcy75e8At66TqElO5MPgjc3LDQCRgnKhUday4TjLimQIDAQAB";

    private static final String CO_PRIVATE_KEY = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAMsFDM3N4rAZAtMNxXqbPhiqrSm2TMvveTJkJRX4vY2gAKix2jiHmZQQjLRnm84TY/m6D6YePeOqjUyjExOcPL9Xs5u1DRSbRgUhrXVAm+E128UeIIGrgHrrDQYazsuW2FbFoPs04BGPU0+yaTUZO3u7d0hobfXL+AMuMMQM+pMLAgMBAAECgYBMpT1uPTpFzUt5rotNfGp3GYiCZOadX21cDt7Jarz1SOC2z15ZVSgv9AeK3ErABCYMU6gwyN4Io4zwz+gV0ThFQE3INHjhaqNyn5UfslM/vP003GvdfgbuKitGcIyuO51Zx6Qipqqn/3sHEiO7HvVJEtbrbYHyUG2g8PM58f8S4QJBAPCc4ClN9RG5hjyS6pANRKfiKtmB8Ts+sQZD9o1f+Svyi8faYk0UFeUKxl+h+W/qYuMu/AFoBqtE8KORvjw8MCkCQQDYALrm2V0gVXVdgFyMennepkAheWZEIkqDct2kNHVAis9DvddEfYwwA+PjEO4ywlpBglyfK9i2dZkwQCzEywATAkBNT/rvCq+OLHCnkgVwl/LRhuiBzzD1+mTjQH8+WfI0XtDvPIqNfcCzQc0P+Xmurj9sBDLRON27toEj7baUoDpRAkA/oj9tgL2hp+tyhz08mVxLznh4JBaPnfaLsQxAsr+UKxCSaVwArmfdQVgibbtusrj6MZhtv/IRFqXxhAZsV02HAkBkvTCFTfSBjt5amXjlK306AsqsxLjdSjcjpWXguzBirPzUkJCOicFhtnKdHbk34Ys8EFE9OF+ptGQVm15cHfB/";


    /**
     * 审批结论
     *
     * @param sendData
     * @return
     */


    private boolean sendOTPByNx(String phone, String content) {

        log.info("== 发送短信 ==,content:{}", content);
        try {
            MultiValueMap<String, String> body = new LinkedMultiValueMap<String, String>();
            body.add("appkey", apolloConfigUtil.getNxSmsOtpAppKey());
            body.add("secretkey", apolloConfigUtil.getNxSmsOtpSecretKey());
            body.add("phone", "91" + phone);
            body.add("content", content);
            body.add("source_address", apolloConfigUtil.getNxSmsOtpSender());
            log.info("== nx 发送验证码 请求==,body:{}", JSON.toJSONString(body));
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

            HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(body, headers);

            RestTemplate restTemplate = new RestTemplate();
            ResponseEntity<String> responseEntity = restTemplate.postForEntity(apolloConfigUtil.getNxSmsUrl(), request, String.class);

            String res = responseEntity.getBody();
            log.info("== nx 发送验证码 结果==,res:{}", res);
            return true;
        } catch (Exception e) {
            log.error("== nx 发送验证码 异常==,e", e);
            return true;
        }
    }

    public static void main1(String[] args) {
        String productName = "RupeeGo";
        MultiValueMap<String, String> body = new LinkedMultiValueMap<String, String>();
        body.add("appkey", "YqLQqb7m");
        body.add("secretkey", "PADueMrk");
        body.add("phone", "918050843289");
        body.add("content", "Congratulations your application of product " + productName + "  passed, please login  RupeeMama check. VASUKS");
        body.add("source_address", "VASUKS");
        log.info("== nx 发送验证码 请求==,body:{}", JSON.toJSONString(body));
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(body, headers);

        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> responseEntity = restTemplate.postForEntity("http://api2.nxcloud.com/api/sms/mtsend", request, String.class);

        String res = responseEntity.getBody();
        log.info("== nx 发送验证码 结果==,res:{}", res);
    }

    public OpenApiResult approveConclusion(ReceiveData sendData) {
        try {
            String merchantCode = sendData.getMerchantCode();
            ProductCategory category = productIntegrationService.getCategoryByMerchantCode(merchantCode);
            if (category == null) {
                return OpenApiResult.failure(OpenApiResultCode.FAILURE, "wrong merchant");
            }

            String merchantPublicKey = category.getMerchantPublicKey();
            ApproveConclusionDTO approveConclusionDTO = JSONObject.parseObject(getBizData(merchantPublicKey, sendData), ApproveConclusionDTO.class);
            if (approveConclusionDTO == null || approveConclusionDTO.getConclusion() == null) {
                return OpenApiResult.failure(OpenApiResultCode.PARAM_ERROR, "wrong params");
            }
            TradeBase entity = tradeBaseRepository.load(approveConclusionDTO.getOrder_no());
            //如果已经返回过审核结果 则不再接受新的审核结果
            if (!entity.getTradeOrderStatus().equals(TradeStatusEnum.AUDIT_WATTING)) {
                return OpenApiResult.success("new audit call back result not accepted");
            }
//            ProductCategory category = productIntegrationService.getCategoryByMerchantCode(entity.getMerchantCode());

            log.info("category:{}", JSON.toJSONString(category));
            log.info("approveConclusionDTO:{}", JSON.toJSONString(approveConclusionDTO));
            if (approveConclusionDTO.getConclusion().equals(ApprovalConclusionEnum.PASS.getCode())) {
                if (entity.getTradeOrderStatus() != TradeStatusEnum.PENDING_WITHDRAWAL) {
                    if (category.getConfirmWithdrawProcess() != null && category.getConfirmWithdrawProcess().equals(1)) {
                        tradeBaseService.auditPassToWithdraw(entity);
                    } else {
                        tradeBaseService.auditPass(entity);
                    }
                }
//                if (approveConclusionDTO.getApproval_time() != 0) {
//                    entity.setAuditDate(new Date(approveConclusionDTO.getApproval_time()));
//                }
                entity.setAuditDate(new Date());
                tradeBaseRepository.restore(entity);
                User userByUserCode = userIntegrationService.getUserByUserCode(entity.getUserCode());
                boolean isRupeemama = userByUserCode.getPackageName().contains("rupeemama");
                String appName = getAppName(userByUserCode.getPackageName());
                sendOTPByNx(userByUserCode.getMobile(), "[" + appName + "] your application of product " + category.getName() + "  passed, please login  " + appName + " check. VASUKS");

            } else if (approveConclusionDTO.getConclusion().equals(ApprovalConclusionEnum.REJECTED.getCode())) {
                if (entity.getTradeOrderStatus() != TradeStatusEnum.AUDIT_REJECT) {
                    tradeBaseService.closeAuditRejectTrade(entity);
                    tradeUniqueService.releaseUniqueLock(entity);
                }
                tradeBaseRepository.restore(entity);
                userIntegrationService.frozenUser(entity.getUserCode(), entity.getProductCategory(), FrozenCodeEnum.BORROW_REJECT);
            } else {
                return OpenApiResult.failure(OpenApiResultCode.PARAM_ERROR, "wrong result type");
            }

            return OpenApiResult.success();
        } catch (ApplicationException e) {
            log.error("审批结论接收失败。。。", e);
            return OpenApiResult.failure(OpenApiResultCode.FAILURE, e.getMessage());
        } catch (Exception e) {
            log.error("回调失败。。。", e);
            return OpenApiResult.failure(OpenApiResultCode.FAILURE);
        }
    }

    public static void main(String[] args) {
//        TimeUtils.
    }

    /**
     * 打款回调
     *
     * @param sendData
     * @return
     */

    public OpenApiResult repaymentPlan(ReceiveData sendData) {
        try {
            if (sendData == null) {
                return OpenApiResult.failure(OpenApiResultCode.PARAM_ERROR);
            }

            String merchantCode = sendData.getMerchantCode();
            ProductCategory category = productIntegrationService.getCategoryByMerchantCode(merchantCode);
            if (category == null) {
                return OpenApiResult.failure(OpenApiResultCode.FAILURE, "product config fail");
            }

            String merchantPublicKey = category.getMerchantPublicKey();
            RepaymentPlanDetailDTO planDetailVO = JSONObject.parseObject(getBizData(merchantPublicKey, sendData), RepaymentPlanDetailDTO.class);

            TradeBase tTradeEntity = tradeBaseRepository.load(planDetailVO.getOrder_no());
            if (tTradeEntity == null) {
                return OpenApiResult.failure(OpenApiResultCode.ORDER_NOR_EXIST);
            }
            if (!tTradeEntity.getTradeOrderStatus().equals(TradeStatusEnum.LOAN_WAITTING)) {
                return OpenApiResult.success("new loan call back result not accepted");
            }

            if (tTradeEntity.getTradeOrderStatus() == TradeStatusEnum.PENDING_WITHDRAWAL) {
                tradeBaseService.loanConfirmSuccess(tTradeEntity);
            } else if (tTradeEntity.getTradeOrderStatus() == TradeStatusEnum.LOAN_WAITTING) {
                tradeBaseService.loanSuccess(tTradeEntity);
                String mobile = userIntegrationService.getUserByUserCode(tTradeEntity.getUserCode()).getMobile();
                User userByUserCode = userIntegrationService.getUserByUserCode(tTradeEntity.getUserCode());
                boolean isRupeemama = userByUserCode.getPackageName().contains("rupeemama");
                String appName = getAppName(userByUserCode.getPackageName());
                sendOTPByNx(mobile, "[" + appName + "] product you applied on " + appName + " has transferred  " + tTradeEntity.getReceivedTotalCapital() + " Rs. to your account. pleach check. VASUKS");
            }

            List<TBillEntity> billEntities = tBillDao.selectListByTradeNo(planDetailVO.getOrder_no());
            buildRepaymentDetail(billEntities, tTradeEntity, planDetailVO);

            return OpenApiResult.success();
        } catch (ApplicationException e) {
            log.error("还款计划接收失败。。。", e);
            return OpenApiResult.failure(OpenApiResultCode.FAILURE, e.getMessage());
        } catch (Exception e) {
            log.error("回调失败。。。", e);
            return OpenApiResult.failure(OpenApiResultCode.FAILURE);
        }
    }

    /**
     * 还款状态
     *
     * @param sendData
     * @return
     */
    @Transactional
    public OpenApiResult repaymentStatus(ReceiveData sendData) {
        try {
            if (sendData == null) {
                return OpenApiResult.failure(OpenApiResultCode.PARAM_ERROR);
            }

            String merchantCode = sendData.getMerchantCode();
            ProductCategory category = productIntegrationService.getCategoryByMerchantCode(merchantCode);
            if (category == null) {
                return OpenApiResult.failure(OpenApiResultCode.FAILURE, "product config fail");
            }

            String merchantPublicKey = category.getMerchantPublicKey();
            RepaymentStatusDTO dto = JSONObject.parseObject(getBizData(merchantPublicKey, sendData), RepaymentStatusDTO.class);

            TradeBase tTradeEntity = tradeBaseRepository.load(dto.getOrder_no());
            if (!tTradeEntity.getTradeOrderStatus().equals(TradeStatusEnum.REPAYMENT_WATTING)) {
                return OpenApiResult.success("new repayment call back result not accepted");
            }

            List<TBillEntity> billEntities = tBillDao.selectListByTradeNo(dto.getOrder_no());
            if (tTradeEntity == null || CollectionUtils.isEmpty(billEntities)) {
                return OpenApiResult.failure(OpenApiResultCode.ORDER_NOR_EXIST);
            }

            if (dto.getRepay_status() == 1) {
                UserAccessInfo userAccessInfo = userIntegrationService.getUserAccessInfoByUserCode(tTradeEntity.getUserCode());
                if (dto.getRepay_status_detail() == TradeStatusEnum.EARLY_REPAYMENT.getStatus()) {
                    tradeBaseService.earlyPayment(tTradeEntity);
                    redisClient.del(RedisKeyConstant.COLLISION_DATA_KEY, userAccessInfo.getMobile(), tTradeEntity.getMerchantCode());
                } else if (dto.getRepay_status_detail() == TradeStatusEnum.NORMAL_REPAYMENT.getStatus()) {
                    log.info("== 正常还款 ==,userAccessInfo:{}", JSON.toJSON(userAccessInfo));
                    tradeBaseService.normalPayment(tTradeEntity);
                    redisClient.del(RedisKeyConstant.COLLISION_DATA_KEY, userAccessInfo.getMobile(), tTradeEntity.getMerchantCode());

                    User userByUserCode = userIntegrationService.getUserByUserCode(tTradeEntity.getUserCode());
                    String mobile = userByUserCode.getMobile();
                    String appName = getAppName(userByUserCode.getPackageName());
                    if (tTradeEntity.getProductCategory().equals("loanZoneAll")) {
                        appName = "LoanZone";
                    } else if (tTradeEntity.getProductCategory().equals("cashZoneAll")) {
                        appName = "CashZone";
                    } else if (tTradeEntity.getProductCategory().equals("meraLoanAll")) {
                        appName = "MeraLoan";
                    }

                    sendOTPByNx(mobile, "[" + appName + "] your bill on " + appName + " of product " + category.getName() + " repayment successful. VASUKS");
                } else if (dto.getRepay_status_detail() == TradeStatusEnum.OVERDUE_REPAYMENT.getStatus()) {
                    tradeBaseService.overduePayment(tTradeEntity);
                    redisClient.del(RedisKeyConstant.COLLISION_DATA_KEY, userAccessInfo.getMobile(), tTradeEntity.getMerchantCode());
                }
                tTradeEntity.setTradePayStatus(TradePayStatusEnum.PAY_SUCCESS);
                tTradeEntity.setPayOffDate(new Date());


                TBillEntity entity = billEntities.get(0);
                entity.setStatus(1);
                entity.setPaidStatus(2);
                entity.setPayOffDate(DateUtil.getDate(dto.getSuccess_time(), "yyyy-MM-dd HH:mm:ss"));
                entity.setPaidCapital(new BigDecimal(dto.getRepay_amount()));
                log.info("trade entity:{}", JSON.toJSONString(tTradeEntity));
                log.info("bill entity:{}", JSON.toJSONString(entity));
                tradeBaseRepository.restore(tTradeEntity);
                tBillDao.updateByPrimaryKey(entity);
                tradeUniqueService.releaseUniqueLock(tTradeEntity);
            }

            return OpenApiResult.success();
        } catch (ApplicationException e) {
            log.error("还款状态接收失败。。。", e);
            return OpenApiResult.failure(OpenApiResultCode.FAILURE, e.getMessage());
        } catch (Exception e) {
            log.error("回调失败。。。", e);
            return OpenApiResult.failure(OpenApiResultCode.FAILURE);
        }
    }


    public static String getAppName(String packageName) {
        boolean isRupeemama = "com.rupeemama.app".equalsIgnoreCase(packageName);
        boolean isCashmall = "com.kly.cm.mall".equalsIgnoreCase(packageName);
        boolean isLoanZone = "com.vayloan.app".equalsIgnoreCase(packageName);
        Map<String, String> map = new HashMap<>();
        map.put("com.rupeemama.app", "RupeeMama");
        map.put("com.kly.cm.mall", "CashMall");
        map.put("com.vayloan.app", "LoanZone");

        if (!map.containsKey(packageName)) {
            return "Dear";
        }

        return map.get(packageName);

    }


    /**
     * 同步订单状态
     *
     * @param sendData
     * @return
     */
    public OpenApiResult orderStatus(ReceiveData sendData) {
        try {
            if (sendData == null) {
                return OpenApiResult.failure(OpenApiResultCode.PARAM_ERROR);
            }


            String merchantCode = sendData.getMerchantCode();
            ProductCategory category = productIntegrationService.getCategoryByMerchantCode(merchantCode);
            if (category == null) {
                return OpenApiResult.failure(OpenApiResultCode.FAILURE, "product config fail");
            }

            String merchantPublicKey = category.getMerchantPublicKey();
            OrderStatusDTO statusDTO = JSONObject.parseObject(getBizData(merchantPublicKey, sendData), OrderStatusDTO.class);

            TradeBase tTradeEntity = tradeBaseRepository.load(statusDTO.getOrder_no());
            if (tTradeEntity == null) {
                return OpenApiResult.failure(OpenApiResultCode.ORDER_NOR_EXIST);
            }
            UserAccessInfo userAccessInfo = userIntegrationService.getUserAccessInfoByUserCode(tTradeEntity.getUserCode());
            if (statusDTO.getOrder_status() != tTradeEntity.getTradeOrderStatus().getStatus()) {
                if (statusDTO.getOrder_status() == TradeStatusEnum.LOAN_WAITTING.getStatus()) {
                    if (tTradeEntity.getTradeOrderStatus() != TradeStatusEnum.PENDING_WITHDRAWAL) {
                        if (category.getConfirmWithdrawProcess() != null && Objects.requireNonNull(category).getConfirmWithdrawProcess().equals(1)) {
                            tradeBaseService.auditPassToWithdraw(tTradeEntity);
                        } else {
                            tradeBaseService.auditPass(tTradeEntity);
                        }
                    }
                } else if (statusDTO.getOrder_status() == TradeStatusEnum.PAY_RETRY.getStatus()) {
                    tradeBaseService.loanFailed(tTradeEntity, false);
                    tradeUniqueService.releaseUniqueLock(tTradeEntity);
                } else if (statusDTO.getOrder_status() == TradeStatusEnum.REPAYMENT_WATTING.getStatus()) {
                    if (tTradeEntity.getTradeOrderStatus() == TradeStatusEnum.PENDING_WITHDRAWAL) {
                        tradeBaseService.loanConfirmSuccess(tTradeEntity);
                    } else {
                        tradeBaseService.loanSuccess(tTradeEntity);
                    }
                } else if (statusDTO.getOrder_status() == TradeStatusEnum.AUDIT_REJECT.getStatus()) {
                    if (tTradeEntity.getTradeOrderStatus() != TradeStatusEnum.AUDIT_REJECT) {
                        tradeBaseService.closeAuditRejectTrade(tTradeEntity);
                        tradeUniqueService.releaseUniqueLock(tTradeEntity);
                    }
                } else if (statusDTO.getOrder_status() == TradeStatusEnum.EARLY_REPAYMENT.getStatus()) {
                    tradeBaseService.earlyPayment(tTradeEntity);
                    tradeUniqueService.releaseUniqueLock(tTradeEntity);
                    redisClient.del(RedisKeyConstant.COLLISION_DATA_KEY, userAccessInfo.getMobile(), tTradeEntity.getMerchantCode());
                } else if (statusDTO.getOrder_status() == TradeStatusEnum.NORMAL_REPAYMENT.getStatus()) {
                    tradeBaseService.normalPayment(tTradeEntity);
                    tradeUniqueService.releaseUniqueLock(tTradeEntity);
                    redisClient.del(RedisKeyConstant.COLLISION_DATA_KEY, userAccessInfo.getMobile(), tTradeEntity.getMerchantCode());
                } else if (statusDTO.getOrder_status() == TradeStatusEnum.OVERDUE_REPAYMENT.getStatus()) {
                    tradeBaseService.overduePayment(tTradeEntity);
                    tradeUniqueService.releaseUniqueLock(tTradeEntity);
                    redisClient.del(RedisKeyConstant.COLLISION_DATA_KEY, userAccessInfo.getMobile(), tTradeEntity.getMerchantCode());
                } else if (statusDTO.getOrder_status() == TradeStatusEnum.PENDING_WITHDRAWAL.getStatus()) {
                    tradeBaseService.auditPassToWithdraw(tTradeEntity);
                } else if (statusDTO.getOrder_status() == TradeStatusEnum.OVERDUE.getStatus()) {
                    tradeBaseService.overdue(tTradeEntity);
                }
                tradeBaseRepository.restore(tTradeEntity);
            }
            return OpenApiResult.success();
        } catch (ApplicationException e) {
            log.error("同步订单状态接收失败。。。", e);
            return OpenApiResult.failure(OpenApiResultCode.FAILURE, e.getMessage());
        } catch (Exception e) {
            log.error("回调失败。。。", e);
            return OpenApiResult.failure(OpenApiResultCode.FAILURE);
        }
    }

    public String getBizData(String merchantKey, ReceiveData sendData) {

        //check  sign
        try {
            Map<String, String> data = new HashMap<>();
            data.put("merchantCode", sendData.getMerchantCode());
            data.put("bizData", sendData.getBizData());
            log.info("== 加密开始 ==,data:{},key:{}", JSON.toJSONString(sendData), merchantKey);
            String signature = SendToMerchantData.generateSignature(data, merchantKey);
            log.info("== 加密结束 ==,sign:{}", signature);
            if (signature.equals(sendData.getSign())) {
                return sendData.getBizData();
            }
        } catch (Exception e) {
            log.error("== 商户回调 签名验证错误 ==", e);
        }

        throw new ApplicationException("sign check failed");
    }

//    public static void main(String[] args) {
//        Map<String, String> data = new HashMap<>();
//        data.put("merchantCode", "HeartCoin");
//        data.put("bizData", "{\"amount_type\":0,\"approval_amount\":0,\"approval_term\":0,\"approval_time\":0,\"conclusion\":10,\"order_no\":\"229840330122331389DC\",\"pro_type\":0,\"term_type\":0,\"term_unit\":0}");
//
//        try {
//            String signature = SendToMerchantData.generateSignature(data, "MIGfMA0GC");
//            System.err.println(signature);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//    }

    /**
     * 获取订单转状态
     *
     * @param request
     * @return
     */
//    public OpenApiResult getOrderStatus(BaseRequest request) {
//        TradeBase tTradeEntity = tradeBaseRepository.load(request.getOrder_no());
//        if (tTradeEntity == null) {
//            return OpenApiResult.failure(OpenApiResultCode.ORDER_NOR_EXIST);
//        }
//
//        Map<String, String> map = new HashMap<>();
//        map.put("order_no", request.getOrder_no());
//
//        ReceiveData sendData = StandardUtil.assemblyReceiverData(JSON.toJSONString(map), SELF_PUBLIC_KEY, CO_PRIVATE_KEY, "gupta.order.status", APP_ID);
//        log.info("send data:{}", JSON.toJSONString(sendData));
//        String response = commonRequest(JSON.toJSONString(sendData));
//        OpenApiResult result = null;
//        try {
//            result = JSONUtils.json2pojoAndOffUnknownField(response, OpenApiResult.class);
//        } catch (Exception e) {
//            log.error("订单状态转换失败", e);
//        }
//        if (Objects.requireNonNull(result).getCode() != 0) {
//            OpenApiResult.failure(OpenApiResultCode.OPEN_API_ERROR);
//        }
//        ProductCategory category = productIntegrationService.getCategoryByMerchantCode(tTradeEntity.getMerchantCode());
//        if (category == null) {
//            return OpenApiResult.failure(OpenApiResultCode.FAILURE, "product config fail");
//        }
//
//        OrderStatusDTO statusDTO = (OrderStatusDTO) result.getData();
//        if (statusDTO.getOrder_status() != tTradeEntity.getTradeOrderStatus().getStatus()) {
//            if (statusDTO.getOrder_status() == TradeStatusEnum.LOAN_WAITTING.getStatus()) {
//                if (category.getConfirmWithdrawProcess().equals(1)) {
//                    tradeBaseService.auditPassToWithdraw(tTradeEntity);
//                } else {
//                    tradeBaseService.auditPass(tTradeEntity);
//                }
//            } else if (statusDTO.getOrder_status() == TradeStatusEnum.PAY_RETRY.getStatus()) {
//                tradeBaseService.loanFailed(tTradeEntity, false);
//                tradeUniqueService.releaseUniqueLock(tTradeEntity);
//            } else if (statusDTO.getOrder_status() == TradeStatusEnum.REPAYMENT_WATTING.getStatus()) {
//                tradeBaseService.paymentSuccess(tTradeEntity);
//            } else if (statusDTO.getOrder_status() == TradeStatusEnum.AUDIT_REJECT.getStatus()) {
//                tradeBaseService.closeAuditRejectTrade(tTradeEntity);
//                tradeUniqueService.releaseUniqueLock(tTradeEntity);
//            } else {

//                tTradeEntity.setTradeOrderStatus(TradeStatusEnum.convertByStatus(statusDTO.getOrder_status()));
//            }
//            tradeBaseRepository.restore(tTradeEntity);
//        }
//        return OpenApiResult.success(statusDTO);
//    }
//
//    /**
//     * 查询还款计划
//     *
//     * @param request
//     * @return
//     */
//    public OpenApiResult getPaymentPlan(BaseRequest request) {
//        if (request == null) {
//            return OpenApiResult.failure(OpenApiResultCode.PARAM_ERROR);
//        }
//        Map<String, String> map = new HashMap<>();
//        map.put("order_no", request.getOrder_no());
//
//        ReceiveData sendData = StandardUtil.assemblyReceiverData(JSON.toJSONString(map), SELF_PUBLIC_KEY, CO_PRIVATE_KEY, "gupta.payment.plan", APP_ID);
//
//        List<TBillEntity> billEntities = tBillDao.selectListByTradeNo(request.getOrder_no());
//        TradeBase tTradeEntity = tradeBaseRepository.load(request.getOrder_no());
//        if (CollectionUtils.isEmpty(billEntities) || tTradeEntity == null) {
//            return OpenApiResult.failure(OpenApiResultCode.ORDER_NOR_EXIST);
//        }
//        String response = commonRequest(JSON.toJSONString(sendData));
//        OpenApiResult result = null;
//        try {
//            result = JSONUtils.json2pojoAndOffUnknownField(response, OpenApiResult.class);
//        } catch (Exception e) {
//            log.error("订单状态转换失败", e);
//        }
//        if (Objects.requireNonNull(result).getCode() != 0) {
//            OpenApiResult.failure(OpenApiResultCode.OPEN_API_ERROR);
//        }
//        RepaymentPlanDetailDTO planDetailVO = (RepaymentPlanDetailDTO) result.getData();
//
//        buildRepaymentDetail(billEntities, tTradeEntity, planDetailVO);
//        return OpenApiResult.success(planDetailVO);
//
//    }


    /**
     * 还款计划
     *
     * @param billEntities
     * @param tTradeEntity
     * @param planDetailVO
     */

    private void buildRepaymentDetail(List<TBillEntity> billEntities, TradeBase tTradeEntity, RepaymentPlanDetailDTO planDetailVO) {
        tTradeEntity.setBorrowTotalCapital(new BigDecimal(planDetailVO.getLoan_amount()));
        tTradeEntity.setReceivedTotalCapital(new BigDecimal(planDetailVO.getReceived_capital()));
        tTradeEntity.setRepaymentTotalCapital(new BigDecimal(planDetailVO.getRepay_amount()));
        tTradeEntity.setBorrowRatio(new BigDecimal(planDetailVO.getInterest_rate()));
        if (planDetailVO.getLoan_time() != 0) {
            tTradeEntity.setReceivedDate(new Date(planDetailVO.getLoan_time()));
        }
        TBillEntity entity;
        if (CollectionUtils.isEmpty(billEntities)) {
            entity = new TBillEntity();
            entity.setBillNo(IdUtils.genId() + "TB");
        } else {
            entity = billEntities.get(0);
        }
        if (planDetailVO.getBill_status() == BillPaidStatusEnum.CLEAR_REPAYMENT.getStatus()) {
            entity.setStatus(1);
            entity.setPaidStatus(BillPaidStatusEnum.CLEAR_REPAYMENT.getStatus());
            entity.setPayOffDate(new Date());
            entity.setOverdueFee(new BigDecimal(0));
            entity.setOverdueServiceFee(new BigDecimal(0));
            if (!planDetailVO.getOrder_status().equals(String.valueOf(tTradeEntity.getTradeOrderStatus().getStatus()))) {
                if (planDetailVO.getOrder_status().equals(OrderStatusSwitchEnum.EARLIER_REPAY_SUCCESS.getCode().toString())) {
                    tradeBaseService.earlyPayment(tTradeEntity);
                } else if (planDetailVO.getOrder_status().equals(OrderStatusSwitchEnum.OVERDUE_REPAY_SUCCESS.getCode().toString())) {
                    tradeBaseService.overduePayment(tTradeEntity);
                } else if (planDetailVO.getOrder_status().equals(OrderStatusSwitchEnum.REPAY_SUCCESS.getCode().toString())) {
                    tradeBaseService.normalPayment(tTradeEntity);
                }
            }
        } else {
            entity.setStatus(BillPaidStatusEnum.INIT.getStatus());
            entity.setPaidStatus(BillPaidStatusEnum.INIT.getStatus());
        }
        entity.setTradeNo(tTradeEntity.getTradeNo());
        entity.setBorrowCapital(new BigDecimal(planDetailVO.getLoan_amount()));
        entity.setReceivedCapital(new BigDecimal(planDetailVO.getReceived_capital()));
        entity.setInterestFee(new BigDecimal(planDetailVO.getInterest_amount()));
        entity.setBorrowServiceFee(new BigDecimal(planDetailVO.getService_amount()));
        entity.setRepaymentCapital(new BigDecimal(planDetailVO.getRepay_amount()));
        entity.setRepaymentDate(new Date(planDetailVO.getExpiry_time()));
        entity.setCurrentPeriod(1);
        entity.setProductCategory(tTradeEntity.getProductCategory());
        entity.setProductCode(tTradeEntity.getProductCode());
        entity.setPaidCapital(new BigDecimal("0"));
        entity.setDiscountCapital(new BigDecimal("0"));
        entity.setCreateDt(new Date());
        if (StringUtils.isNotEmpty(planDetailVO.getPaid_capital())) {
            entity.setPaidCapital(new BigDecimal(planDetailVO.getPaid_capital()));
        }
        if (StringUtils.isNotEmpty(planDetailVO.getOverdue_service_fee())) {
            entity.setOverdueServiceFee(new BigDecimal(planDetailVO.getOverdue_service_fee()));
        }
        if (planDetailVO.getBill_status() == 3 && StringUtils.isNotEmpty(planDetailVO.getOverdue_service_fee())) {
            entity.setOverdueServiceFee(new BigDecimal(planDetailVO.getOverdue_service_fee()));
        }
        if (planDetailVO.getBill_status() == 3) {
            entity.setOverdueFee(new BigDecimal(planDetailVO.getExpiry_amount()));
        }
        //更新trade
        tradeBaseRepository.restore(tTradeEntity);
        //更新bill
        if (entity.getId() == null || entity.getId() == 0L) {
            tBillDao.insert(entity);
        } else {
            tBillDao.updateByPrimaryKey(entity);
        }
    }


    public String commonRequest(String body) {
        try {
            Map<String, String> headers = new HashMap<>();
//            headers.put("token", token);
            return HttpUtil.postPageBody(pushUrlDomain, headers, body);
        } catch (Exception e) {
            log.error("请求open-api出错。。。", e);
            return null;
        }
    }


}
